package util


import "fmt"
import "api"
import "vm"


func PrintStack(ls api.LuaState) {

	top := ls.GetTop()

	for i := 1; i <= top; i++ {

		t := ls.Type(i)
		switch t {
			case api.LUA_TBOOLEAN: 	fmt.Printf("[%t]", ls.ToBoolean(i))

			case api.LUA_TNUMBER:	fmt.Printf("[%g]", ls.ToNumber(i))

			case api.LUA_TSTRING:	fmt.Printf("[%q]", ls.ToString(i))

			default:				fmt.Printf("[%s]", ls.TypeName(t))
		}
	}

	fmt.Printf("\n")
}


func PrintInstruction(pc int64, c vm.Instruction) {
	line := "-"

	// fmt.Printf("\t%d\t[%s]\t0x%08X\n", pc+1, line, c)

	i := vm.Instruction(c)

	fmt.Printf("\t%d\t[%s]\t%s \t", pc+1, line, i.OpName())

	printOperands(i)

	fmt.Printf("\n")
}


// 打印指令的操作数
func printOperands(i vm.Instruction) {

	switch i.OpMode() {
	case vm.IABC: printIABCOperands(i); break
	case vm.IABx: printIABxOperands(i); break
	case vm.IAsBx: printIAsBxOperands(i); break
	case vm.IAx: printIAxOperands(i); break
	}
}


// 打印IABC指令的操作数
func printIABCOperands(i vm.Instruction) {

	a, b, c := i.ABC()

	fmt.Printf("%d", a)

	if i.BMode() != vm.OpArgN {  // 操作数不是未被使用
		if b > 0xFF {  // 操作数B的最高位是1，就认为它是常量索引，按负数输出
			fmt.Printf(" %d", -1-(b&0xFF))
		} else {
			fmt.Printf(" %d", b)
		}
	}

	if i.CMode() != vm.OpArgN {  // 操作数不是未被使用
		if c > 0xFF {  // 操作数B的最高位是1，就认为它是常量索引，按负数输出
			fmt.Printf(" %d", -1-(c&0xFF))
		} else {
			fmt.Printf(" %d", c)
		}
	}
}


// 打印IABx指令的操作数
func printIABxOperands(i vm.Instruction) {

	a, bx := i.ABx()

	fmt.Printf("%d", a)

	if i.BMode() == vm.OpArgK {  // 常量索引，按负数形式输出
		fmt.Printf(" %d", -1-bx)
	} else if i.BMode() == vm.OpArgU {
		fmt.Printf(" %d", bx)
	}
}


// 打印IAsBx指令的操作数
func printIAsBxOperands(i vm.Instruction) {

	a, sbx := i.AsBx()

	fmt.Printf("%d %d", a, sbx)
}


// 打印IAx指令的操作数
func printIAxOperands(i vm.Instruction) {

	ax := i.Ax()

	fmt.Printf("%d", -1-ax)
}